home *** CD-ROM | disk | FTP | other *** search
- #include "c_includ.h"
- /*
- * cbzone_scores.c
- * -- Todd W Mummert, December 1990, CMU
- *
- * RCS Info
- * $Header: c_scores.c,v 1.1 91/01/12 02:03:36 mummert Locked $
- *
- * Derived from work I did on our local version of golddig. Thanks
- * to Bennet Yee (CMU) for the flock() code.
- */
-
- /*
- * Okay, let's try to clean this up. The following things may
- * happen:
- * score < 0: then the user is just asking for scores. the score
- * file should not be changed.
- * score >= 0: score is either valid, for practice, or played by an
- * old version. In all cases, the file should change.
- *
- * file status:
- * can be not there
- * available for reading
- * available for both reading and writing
- * not there but can be written
- *
- * we know the following:
- * whether the game was for practice only.
- * any scores in the score file WILL be in the correct order.
- *
- * the format of the score file is as follows:
- * Version identification
- * number of games played, followed by number of valid games
- * scores, one per line w/uid and player's name
- *
- * how should we go about comparing users?
- * use getuid and cuserid...check both of them since we may be
- * saving scores over a distributed file system
- *
- * if the game was scoresonly, print to tty if opt->output allows;
- * else print to X screen.
- */
-
- extern int errno;
- int x, y, ydelta;
-
-
- void xprintf(s, output) /* print to the X screen */
- char* s;
- Bool output;
- {
- printstring (x, y, s, strlen(s));
- y += ydelta;
- }
-
- void nprintf(s, output) /* print to the parent tty */
- char* s;
- Bool output;
- {
- if (output)
- printf("%s\n", s);
- }
-
- void printandwait(s, c) /* print a string and then */
- char* s; /* wait for a character c */
- char c; /* to be pressed. If c==0 */
- { /* then any keypress will */
- y += ydelta; /* do. */
- xprintf(s, True);
- waitforkey(c);
- }
-
- LONG scores(score)
- LONG score;
- {
- struct score_struct {
- LONG score;
- int uid;
- char name[50];
- struct score_struct *next;
- } player, *current, *top_score, *prev_score;
-
- FILE *sfile;
- char buf[100];
- char version[100];
- char *login, *getlogin();
- int i;
- Font fontid;
- int numgame = 0;
- int numscore = 0;
- int numscoreable = 0;
- int player_scores = 0;
- int tries = MAX_RETRIES;
- Bool score_printed = False;
- Bool scoresonly = False;
- Bool wrong_version = False;
- Bool file_readable = False;
- Bool file_writeable = False;
- Bool practice = opt->practice;
- struct passwd* pw;
- void (*p)();
-
- version[0] ='\0';
- if (score < 0) {
- practice = True;
- scoresonly = True;
- p = nprintf;
- }
- else {
- p = xprintf;
- gprsetclippingactive(False);
- fontid = gprloadfontfile(GAMEOVERFONT);
- gprsettextfont(fontid);
- printstring (165, 300, "GAME OVER", 9);
- fontid = gprloadfontfile(GENERALFONT);
- gprsettextfont(fontid);
- printstring (165, 320, "1986 JSR", 8);
- flushwindow();
- sleep(1);
- clearentirescreen();
- }
-
- x = 350;
- y = 100;
- ydelta = 15;
-
- sprintf(buf,"%s%s",TANKDIR,SCOREFILE);
- sfile = fopen(buf,"r"); /* just check if it is there */
-
- if (sfile == NULL) {
- p("Score file not readable.", opt->output);
- if (scoresonly)
- return 1;
- else {
- p("Will try and create new scorefile.", opt->output);
- }
- }
- else
- file_readable = True;
-
- if (!scoresonly) {
- (void) signal(SIGINT, SIG_IGN); /* no leaving this routine */
- (void) signal(SIGHUP, SIG_IGN); /* no how, no way */
- file_writeable = True;
- if (sfile != NULL)
- fclose(sfile);
-
- retry:
- if (file_readable)
- sfile = fopen(buf,"r+"); /* okay, now open for update */
- else
- sfile = fopen(buf,"w");
-
- if (sfile != NULL) {
- if (flock(fileno(sfile),LOCK_EX) < 0) {
- if (errno == EWOULDBLOCK && AFS) {
- fclose(sfile);
- sleep(AFS_SLEEP);
- if (tries--)
- goto retry;
- }
- p("File not lockable, scores will not be saved.", opt->output);
- file_writeable = False;
- }
- }
- else {
- p("File not writeable, scores will not be saved.", opt->output);
- file_writeable = False;
- }
-
- /* okay, it's possible we could have closed the file and never
- * reopened it. Also, we just may not have been able to lock
- * it. In either case, lets close it again and then open only
- * for reading.
- */
- if (file_readable && !file_writeable) {
- if (sfile != NULL)
- fclose(sfile);
- if ((sfile = fopen(buf, "r")) == NULL)
- file_readable = False;
- }
- }
-
- if (!file_readable && !file_writeable) {
- p("Scorefile not readable or writeable...Goodbye!", opt->output);
- (void) signal(SIGINT, SIG_DFL); /* this would probably happen */
- (void) signal(SIGHUP, SIG_DFL); /* on exit anyway */
- if (!scoresonly)
- printandwait("Press any key to continue...", 0);
- return 1;
- }
-
- if (file_readable) {
- if(fgets(version,200,sfile) && file_writeable) {
- version[strlen(version)-1] = '\0'; /* strip the newline */
- if (strcmp(version,VERSION)) {
- wrong_version = True;
- p("Incorrect version played for this scorefile.", opt->output);
- p("Score not valid for inclusion.", opt->output);
- sprintf(buf,"Your version is \"%s\", while",VERSION);
- p(buf, opt->output);
- sprintf(buf, " the scorefile version is \"%s\"", version);
- p(buf, opt->output);
- }
- }
-
- if (*version == '\0')
- strcpy(version,VERSION);
-
- if(fgets(buf,200,sfile))
- sscanf(buf,"%d %d",&numgame,&numscoreable);
- top_score = (struct score_struct*) malloc(sizeof(struct score_struct));
- current = top_score;
-
- while(fgets(buf,200,sfile) && numscore < NUMHIGH)
- if (sscanf(buf,"%d %d %[^\n]",¤t->score,
- ¤t->uid,current->name) != 3) {
- p("Invalid line in score file...Skipping.", opt->output);
- }
- else {
- current->next = (struct score_struct*)
- malloc(sizeof(struct score_struct));
- prev_score = current;
- current = current->next;
- numscore ++;
- }
- }
-
- if (numscore)
- prev_score->next = NULL;
- else
- top_score = NULL;
-
- if (numgame < numscoreable)
- numgame = numscoreable;
-
- if (!scoresonly) {
- /* try to get it from the passwd file first, just in case this
- * person su'd from another acct.
- */
- player.uid = getuid();
- player.score = score;
- pw = getpwuid(player.uid);
- if (pw == NULL)
- if ((login = getlogin()) != NULL)
- strcpy(player.name, login);
- else {
- p("Can't find out who you are....bye.", opt->output);
- fclose(sfile);
- (void) signal(SIGINT, SIG_DFL);
- (void) signal(SIGHUP, SIG_DFL);
- if (!scoresonly)
- printandwait("Press any key to continue...", 0);
- return 1;
- }
- else
- strcpy(player.name, pw->pw_name);
-
- if (numscore < NUMHIGH || player.score > prev_score->score) {
- score_printed = True;
- numscore++;
-
- for (current = top_score;
- current != NULL && player.score <= current->score;
- prev_score = current, current = current->next);
-
- player.next = current;
-
- if (current == top_score)
- top_score = &player;
- else
- prev_score->next = &player;
- }
-
- numgame++;
- if (!practice && !wrong_version)
- numscoreable++;
- }
-
- sprintf(buf, "High scores after %d games, %d scoreable:",
- numgame, numscoreable);
- p(buf, opt->output);
- current = top_score;
- while (current != NULL) {
- if (current == &player)
- *buf = '>';
- else
- *buf = ' ';
- sprintf(buf+1, "%-20s %8d", current->name, current->score);
- p(buf, opt->output);
-
- if (((wrong_version || practice) && current==&player) ||
- (current->uid==player.uid && !strcmp(player.name, current->name) &&
- ++player_scores>INDIVIDUAL_SCORES)) {
- numscore--;
- if (current == top_score)
- top_score = current->next;
- else
- prev_score->next = current->next;
- }
- else
- prev_score = current;
- current = current->next;
- }
-
- if (!scoresonly && !score_printed) {
- p("...", opt->output);
- sprintf(buf, ">%-20s %8d", player.name,player.score);
- p(buf, opt->output);
- }
-
- if (file_writeable) {
- rewind(sfile);
- fprintf(sfile,"%s\n",version);
- fprintf(sfile,"%d %d\n",numgame,numscoreable);
- for(current = top_score, i = 0;
- current != NULL && i < NUMHIGH;
- current = current->next, i++)
- fprintf(sfile,"%d %d %s\n",current->score,current->uid,current->name);
- if (practice) {
- y += ydelta;
- p("Your game was for practice only...", opt->output);
- p("For a valid score use: cbzone [-q] [-d 0-5]", opt->output);
- }
- }
-
- fclose(sfile);
- (void) signal(SIGINT, SIG_DFL);
- (void) signal(SIGHUP, SIG_DFL);
-
- if (!scoresonly)
- printandwait("Press any key when ready...", 0);
-
- return 0;
- }
-